Changeset 36375 for trunk/psModules
- Timestamp:
- Dec 10, 2013, 2:55:11 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 36 edited
- 1 copied
-
. (modified) (1 prop)
-
psModules (modified) (1 prop)
-
psModules/src/camera/pmFPAfile.c (modified) (1 diff)
-
psModules/src/camera/pmFPAfile.h (modified) (1 diff)
-
psModules/src/camera/pmFPAfileDefine.c (modified) (1 diff)
-
psModules/src/camera/pmFPAfileIO.c (modified) (7 diffs)
-
psModules/src/config/pmConfig.c (modified) (1 diff)
-
psModules/src/objects/Makefile.am (modified) (1 diff)
-
psModules/src/objects/models/pmModel_DEV.c (modified) (1 diff)
-
psModules/src/objects/models/pmModel_EXP.c (modified) (3 diffs)
-
psModules/src/objects/models/pmModel_SERSIC.c (modified) (1 diff)
-
psModules/src/objects/pmModel.c (modified) (1 diff)
-
psModules/src/objects/pmModelFuncs.h (modified) (1 diff)
-
psModules/src/objects/pmModelUtils.c (modified) (3 diffs)
-
psModules/src/objects/pmModel_CentralPixel.c (modified) (2 diffs)
-
psModules/src/objects/pmPCM_MinimizeChisq.c (modified) (8 diffs)
-
psModules/src/objects/pmPCMdata.c (modified) (14 diffs)
-
psModules/src/objects/pmPCMdata.h (modified) (3 diffs)
-
psModules/src/objects/pmSource.c (modified) (4 diffs)
-
psModules/src/objects/pmSource.h (modified) (2 diffs)
-
psModules/src/objects/pmSourceExtendedPars.c (modified) (1 diff)
-
psModules/src/objects/pmSourceExtendedPars.h (modified) (2 diffs)
-
psModules/src/objects/pmSourceFitModel.c (modified) (2 diffs)
-
psModules/src/objects/pmSourceFitModel.h (modified) (1 diff)
-
psModules/src/objects/pmSourceFitPCM.c (modified) (3 diffs)
-
psModules/src/objects/pmSourceFitSet.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO.c (modified) (14 diffs)
-
psModules/src/objects/pmSourceIO.h (modified) (2 diffs)
-
psModules/src/objects/pmSourceIO_CFF.c (copied) (copied from branches/eam_branches/ipp-20130904/psModules/src/objects/pmSourceIO_CFF.c )
-
psModules/src/objects/pmSourceIO_CMF.c.in (modified) (13 diffs)
-
psModules/src/objects/pmSourceIO_PS1_CAL_0.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_PS1_DEV_0.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_PS1_DEV_1.c (modified) (1 diff)
-
psModules/src/objects/pmSourceIO_SMPDATA.c (modified) (1 diff)
-
psModules/src/objects/pmSourceMasks.h (modified) (1 diff)
-
psModules/src/objects/pmSourceMoments.c (modified) (18 diffs)
-
psModules/src/objects/pmSourcePhotometry.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
trunk/psModules
- Property svn:mergeinfo changed
-
trunk/psModules/src/camera/pmFPAfile.c
r33913 r36375 491 491 if (!strcasecmp(type, "CMF")) { 492 492 return PM_FPA_FILE_CMF; 493 } 494 if (!strcasecmp(type, "CFF")) { 495 return PM_FPA_FILE_CFF; 493 496 } 494 497 if (!strcasecmp(type, "WCS")) { -
trunk/psModules/src/camera/pmFPAfile.h
r33913 r36375 34 34 PM_FPA_FILE_CMP, 35 35 PM_FPA_FILE_CMF, 36 PM_FPA_FILE_CFF, 36 37 PM_FPA_FILE_WCS, 37 38 PM_FPA_FILE_RAW, -
trunk/psModules/src/camera/pmFPAfileDefine.c
r35561 r36375 103 103 104 104 type = psMetadataLookupStr(&status, data, "FILE.TYPE"); 105 if (!type) { 106 psError(PM_ERR_CONFIG, true, "FILE.TYPE is not defined for %s\n", name); 107 psFree(file); 108 return NULL; 109 } 110 105 111 file->type = pmFPAfileTypeFromString(type); 106 112 if (file->type == PM_FPA_FILE_NONE) { 107 psError(PM_ERR_CONFIG, true, "FILE.TYPE is not defined for %s\n", name);113 psError(PM_ERR_CONFIG, true, "FILE.TYPE %s is not registered in pmFPAfile.c:pmFPAfileTypeFromString\n", type); 108 114 psFree(file); 109 115 return NULL; -
trunk/psModules/src/camera/pmFPAfileIO.c
r35561 r36375 222 222 case PM_FPA_FILE_CMP: 223 223 case PM_FPA_FILE_CMF: 224 case PM_FPA_FILE_CFF: 224 225 case PM_FPA_FILE_WCS: 225 226 case PM_FPA_FILE_SRCTEXT: … … 317 318 case PM_FPA_FILE_CMP: 318 319 case PM_FPA_FILE_CMF: 320 case PM_FPA_FILE_CFF: 319 321 case PM_FPA_FILE_WCS: 320 322 case PM_FPA_FILE_PSF: … … 483 485 case PM_FPA_FILE_CMP: 484 486 case PM_FPA_FILE_CMF: 487 case PM_FPA_FILE_CFF: 485 488 status = pmFPAviewWriteObjects (view, file, config); 486 489 break; … … 567 570 case PM_FPA_FILE_PATTERN: 568 571 case PM_FPA_FILE_CMF: 572 case PM_FPA_FILE_CFF: 569 573 case PM_FPA_FILE_WCS: 570 574 case PM_FPA_FILE_PSF: … … 643 647 case PM_FPA_FILE_CMP: 644 648 case PM_FPA_FILE_CMF: 649 case PM_FPA_FILE_CFF: 645 650 case PM_FPA_FILE_WCS: 646 651 case PM_FPA_FILE_PSF: … … 804 809 case PM_FPA_FILE_PATTERN: 805 810 case PM_FPA_FILE_CMF: 811 case PM_FPA_FILE_CFF: 806 812 case PM_FPA_FILE_WCS: 807 813 case PM_FPA_FILE_PSF: … … 1016 1022 case PM_FPA_FILE_CMP: 1017 1023 case PM_FPA_FILE_WCS: 1024 case PM_FPA_FILE_CFF: 1018 1025 case PM_FPA_FILE_JPEG: 1019 1026 case PM_FPA_FILE_KAPA: -
trunk/psModules/src/config/pmConfig.c
r34234 r36375 1860 1860 } 1861 1861 1862 return psMetadataLookupMetadata( NULL, filerules, realname);1862 return psMetadataLookupMetadata(&mdok, filerules, realname); 1863 1863 } 1864 1864 -
trunk/psModules/src/objects/Makefile.am
r36085 r36375 40 40 pmSourceIO_SX.c \ 41 41 pmSourceIO_CMP.c \ 42 pmSourceIO_CFF.c \ 42 43 pmSourceIO_SMPDATA.c \ 43 44 pmSourceIO_PS1_DEV_0.c \ -
trunk/psModules/src/objects/models/pmModel_DEV.c
r36106 r36375 269 269 270 270 // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width 271 float scale = moments->Mrf / axes.major; 271 // the factor of 2.3 comes from Table 1 of Graham and Driver (2005) 272 float scale = moments->Mrf / axes.major / 2.3; 272 273 axes.major *= scale; 273 274 axes.minor *= scale; -
trunk/psModules/src/objects/models/pmModel_EXP.c
r36106 r36375 63 63 // 0.5 PIX: the parameters are defined in terms of pixel coords, so the incoming pixcoords 64 64 // values need to be pixel coords 65 // 66 67 // Notes on changing kappa value from 1.70056 to 1.678 68 // I'm using a functional form f(x,y) = Io exp(-kappa (r / r_e)). 69 // The article by Graham & Driver (2005) uses a form Ie exp(-bn [(r / r_e) -1]) 70 // which is equal to Ie exp(-bn (r / r_e)) exp(bn). 71 // Thus, my Io = Ie exp(bn) and my kappa is their bn. 72 // My value of kappa is 1.700, their value for bn is 1.678., so I am off by a small amount there (1.5%). 73 74 75 #define KAPPA_EXP 1.678 76 #define OLD_KAPP_EXP 1.70056 77 65 78 66 79 // Lax parameter limits … … 109 122 // for EXP, we can hard-wire kappa(1): 110 123 // float index = 1.0; 111 float kappa = 1.70056;124 float kappa = KAPPA_EXP; 112 125 113 126 // sqrt(z) is r … … 318 331 319 332 // static value for EXP: 320 float kappa = 1.70056;333 float kappa = KAPPA_EXP; 321 334 322 335 // f = Io exp(-kappa*sqrt(z)) -> sqrt(z) = ln(Io/f) / kappa -
trunk/psModules/src/objects/models/pmModel_SERSIC.c
r36085 r36375 75 75 76 76 // Lax parameter limits 77 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0. 1};77 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.0625 }; 78 78 static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 1.0 }; 79 79 -
trunk/psModules/src/objects/pmModel.c
r34498 r36375 217 217 // the options allow us to modify various aspects of the model 218 218 if (mode & PM_MODEL_OP_NORM) { 219 // if we are including the sky, renormalizing should force use to normalized down the sky flux 220 params->data.F32[PM_PAR_SKY] /= params->data.F32[PM_PAR_I0]; 219 221 params->data.F32[PM_PAR_I0] = 1.0; 220 222 } 221 223 if (!(mode & PM_MODEL_OP_SKY)) { 222 224 params->data.F32[PM_PAR_SKY] = 0.0; 223 } 225 } 224 226 if (mode & PM_MODEL_OP_CENTER) { 225 227 params->data.F32[PM_PAR_XPOS] = image->col0 + 0.5*image->numCols; -
trunk/psModules/src/objects/pmModelFuncs.h
r35560 r36375 36 36 37 37 typedef enum { 38 PM_MODEL_STATUS_NONE = 0x00, ///< model fit not yet attempted, no other info 39 PM_MODEL_STATUS_FITTED = 0x01, ///< model fit completed 40 PM_MODEL_STATUS_NONCONVERGE = 0x02, ///< model fit did not converge 41 PM_MODEL_STATUS_OFFIMAGE = 0x04, ///< model fit drove out of range 42 PM_MODEL_STATUS_BADARGS = 0x08, ///< model fit called with invalid args 43 PM_MODEL_STATUS_LIMITS = 0x10, ///< model parameters hit limits 44 PM_MODEL_STATUS_WEAK_FIT = 0x20, ///< model fit met loose tolerance, but not tight tolerance 38 PM_MODEL_STATUS_NONE = 0x000, ///< model fit not yet attempted, no other info 39 PM_MODEL_STATUS_FITTED = 0x001, ///< model fit completed 40 PM_MODEL_STATUS_NONCONVERGE = 0x002, ///< model fit did not converge 41 PM_MODEL_STATUS_OFFIMAGE = 0x004, ///< model fit drove out of range 42 PM_MODEL_STATUS_BADARGS = 0x008, ///< model fit called with invalid args 43 PM_MODEL_STATUS_LIMITS = 0x010, ///< model parameters hit limits 44 PM_MODEL_STATUS_WEAK_FIT = 0x020, ///< model fit met loose tolerance, but not tight tolerance 45 PM_MODEL_STATUS_NAN_CHISQ = 0x040, ///< model fit failed with a NAN chisq 46 PM_MODEL_SERSIC_PCM_FAIL_GUESS = 0x080, ///< sersic model fit failed on the initial moments-based guess 47 PM_MODEL_SERSIC_PCM_FAIL_GRID = 0x100, ///< sersic model fit failed on the grid search 48 PM_MODEL_PCM_FAIL_GUESS = 0x200, ///< non-sersic model fit failed on the initial moments-based guess 49 PM_MODEL_BEST_FIT = 0x400, ///< this model was the best fit and was subtracted 45 50 } pmModelStatus; 46 51 -
trunk/psModules/src/objects/pmModelUtils.c
r36287 r36375 129 129 bool pmModelAxesToParams (float *Sxx, float *Sxy, float *Syy, psEllipseAxes axes, bool useReff) { 130 130 131 // restrict axex to 0.5 here not below 132 if (axes.minor < 0.2) axes.minor = 0.2; 133 if (axes.major < 0.2) axes.major = 0.2; 134 131 135 psEllipseShape shape = psEllipseAxesToShape (axes); 132 136 … … 137 141 // set the shape parameters 138 142 if (useReff) { 139 *Sxx = PS_MAX(0.5, shape.sx); 140 *Syy = PS_MAX(0.5, shape.sy); 143 // *Sxx = PS_MAX(0.5, shape.sx); 144 // *Syy = PS_MAX(0.5, shape.sy); 145 *Sxx = shape.sx; 146 *Syy = shape.sy; 141 147 *Sxy = shape.sxy * 2.0; 142 148 } else { 143 *Sxx = PS_MAX(0.5, M_SQRT2*shape.sx); 144 *Syy = PS_MAX(0.5, M_SQRT2*shape.sy); 149 // *Sxx = PS_MAX(0.5, M_SQRT2*shape.sx); 150 // *Syy = PS_MAX(0.5, M_SQRT2*shape.sy); 151 *Sxx = M_SQRT2*shape.sx; 152 *Syy = M_SQRT2*shape.sy; 145 153 *Sxy = shape.sxy; 146 154 } … … 193 201 if (!isfinite(axes.minor)) return false; 194 202 if (!isfinite(axes.theta)) return false; 203 if (axes.major == 0) return false; 195 204 196 205 // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width -
trunk/psModules/src/objects/pmModel_CentralPixel.c
r36085 r36375 695 695 int npix = 0; 696 696 697 float kappa = -0.275552 + 1.972625*Sindex + 0.003487 * PS_SQR(Sindex); 697 // -0.275552 + 1.972625*Sindex + 0.003487 * PS_SQR(Sindex); 698 float kappa = pmSersicKappa (Sindex); 698 699 float rindex = 0.5 / Sindex; 699 700 … … 703 704 704 705 float delta = 1.0 / (float) Nsub; 705 float off = -Nsub2 * delta; 706 for (float ix = off; ix < 0.5; ix += delta) { 707 for (float iy = off; iy < 0.5; iy += delta) { 708 709 float dX = dx + ix; 710 float dY = dy + iy; 706 // float off = -Nsub2 * delta; 707 708 int Sx = (int) floor(dx / delta); 709 int Sy = (int) floor(dy / delta); 710 711 for (int ix = -Nsub2; ix <= Nsub2; ix++) { 712 float dX = delta * (Sx + ix); 713 for (int iy = -Nsub2; iy <= Nsub2; iy++) { 714 float dY = delta * (Sy + iy); 711 715 float z = PS_SQR(dX / Rxx) + PS_SQR(dY / Ryy) + dX * dY * Rxy; 712 716 713 717 float q = pow (z, rindex); 714 718 float f = exp(-kappa*q); 719 720 // if ((ix == 0) && (iy == 0)) { 721 // // fprintf (stderr, "this: %f %f %f -- full : %f %f\n", z, q, f, flux, (float) npix); 722 // } 715 723 716 724 flux += f; -
trunk/psModules/src/objects/pmPCM_MinimizeChisq.c
r36085 r36375 135 135 } 136 136 137 if (min->isInteractive) { 138 fprintf (stderr, "%d : ", min->iter); 139 for (int ti = 0; ti < params->n; ti++) { 140 fprintf (stderr, "%f ", params->data.F32[ti]); 141 } 142 fprintf (stderr, " : %f\n", min->value); 143 } 144 137 145 char key[10]; // used for interactive responses 138 146 bool testValue = false; … … 140 148 // set a new guess for Alpha, Beta, Params 141 149 if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) { 142 if ( min->isInteractive) {150 if (false && min->isInteractive) { 143 151 fprintf (stdout, "guess failed (singular matrix or NaN values), continue? [Y,n] "); 144 152 if (!fgets(key, 8, stdin)) { … … 167 175 } 168 176 169 if ( min->isInteractive) {177 if (false && min->isInteractive) { 170 178 p_psVectorPrint(psTraceGetDestination(), Params, "current parameters: "); 171 179 fprintf (stdout, "last chisq : %f\n", min->value); … … 473 481 # else 474 482 if (pcm->use1Dgauss) { 475 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 476 // * the model flux is not masked 477 // * threading takes place above this level 478 pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type); 479 psImageSmooth_PreAlloc_F32 (pcm->modelConvFlux, pcm->smdata); 480 // psImageSmooth (pcm->modelConvFlux, pcm->sigma, pcm->nsigma); 483 484 if (USE_1D_CACHE) { 485 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 486 // * the model flux is not masked 487 // * threading takes place above this level 488 pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type); 489 psImageSmoothCache_F32 (pcm->modelConvFlux, pcm->smdata); 490 } else { 491 pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type); 492 psImageSmooth2dCache_F32 (pcm->modelConvFlux, pcm->smdata2d); 493 } 481 494 } else { 482 495 psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT); … … 493 506 # else 494 507 if (pcm->use1Dgauss) { 495 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 496 // * the model flux is not masked 497 // * threading takes place above this level 498 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 499 psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata); 500 // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma); 508 if (USE_1D_CACHE) { 509 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 510 // * the model flux is not masked 511 // * threading takes place above this level 512 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 513 psImageSmoothCache_F32 (dmodelConv, pcm->smdata); 514 } else { 515 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 516 psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d); 517 } 501 518 } else { 502 519 psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT); … … 514 531 515 532 if (pcm->use1Dgauss) { 516 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 517 // * the model flux is not masked 518 // * threading takes place above this level 519 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 520 psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata); 521 // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma); 533 if (USE_1D_CACHE) { 534 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 535 // * the model flux is not masked 536 // * threading takes place above this level 537 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 538 psImageSmoothCache_F32 (dmodelConv, pcm->smdata); 539 } else { 540 dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type); 541 psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d); 542 } 522 543 } else { 523 544 psImageConvolveFFT (dmodelConv, dmodel, NULL, 0, pcm->psf); … … 541 562 static int Npass = 0; 542 563 char name[128]; 543 snprintf (name, 128, "psf.%03d.fits", Npass); psphotSaveImage (NULL, pcm->psf->image, name); 564 if (!pcm->use1Dgauss) { 565 snprintf (name, 128, "psf.%03d.fits", Npass); psphotSaveImage (NULL, pcm->psf->image, name); 566 } 544 567 snprintf (name, 128, "mod.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelFlux, name); 545 568 snprintf (name, 128, "cnv.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelConvFlux, name); … … 579 602 580 603 float ymodel = pcm->modelConvFlux->data.F32[i][j]; 581 float yweight = 1.0 / source->variance->data.F32[i][j]; 604 605 // XXXX note this point here::: 606 float yweight = pcm->poissonErrors ? 1.0 / source->variance->data.F32[i][j] : 1.0; 582 607 float delta = ymodel - source->pixels->data.F32[i][j]; 583 608 -
trunk/psModules/src/objects/pmPCMdata.c
r36089 r36375 43 43 44 44 # define USE_DELTA_PSF 0 45 # define USE_1D_GAUSS 146 45 47 46 static void pmPCMdataFree (pmPCMdata *pcm) { … … 58 57 psFree (pcm->psfFFT); 59 58 psFree (pcm->constraint); 59 60 60 psFree (pcm->smdata); // pre-allocated data for psImageSmooth_PreAlloc 61 psFree (pcm->smdata2d); // pre-allocated data for psImageSmooth_PreAlloc 61 62 return; 62 63 } … … 88 89 } 89 90 91 pcm->smdata = NULL; 92 pcm->smdata2d = NULL; 93 90 94 pcm->modelConv = NULL; 91 95 pcm->psf = NULL; … … 94 98 pcm->nDOF = 0; 95 99 100 pcm->poissonErrors = true; 101 96 102 // full convolution with the PSF is expensive. if we have to save time, we can do a 1D 97 103 // convolution with a Gaussian approximation to the kernel 98 104 pcm->use1Dgauss = false; 99 pcm->nsigma = 3.0;105 pcm->nsigma = NAN; // this is set to something defined by the user 100 106 pcm->sigma = 1.0; // this should be set to something sensible when the psf is known 101 107 … … 248 254 } 249 255 256 static int modelType_GAUSS = -1; 257 static int modelType_PS1_V1 = -1; 258 259 // generate a Gaussian smoothing kernel for supplied sigma. sigma here does not need to match 260 // that used to allocate the structure, but it is recommended 261 bool psImageSmoothCacheKernel_PS1_V1 (psImageSmoothCacheData *smdata, float sigma, float kappa) { 262 // check for NULL structure elements? 263 264 int size = smdata->Nrange; 265 266 psFree (smdata->kernel); 267 smdata->kernel = psVectorAlloc(2 * smdata->Nrange + 1, PS_TYPE_F32); 268 269 double sum = 0.0; // Sum of Gaussian, for normalization 270 double factor = 1.0 / (sigma * M_SQRT2); // Multiplier for i -> z 271 272 // PS1_V1 is a power-law with fitted linear term: 273 // 1 / (1 + kappa z + z^1.666) where z = (r/sigma)^2 274 275 // generate the kernel (not normalized) 276 for (int i = -size, j = 0; i <= size; i++, j++) { 277 float z = PS_SQR(i * factor); 278 sum += smdata->kernel->data.F32[j] = 1.0 / (1 + kappa * z + pow(z,1.666)); 279 } 280 281 // renormalize kernel to integral of 1.0 282 for (int i = 0; i < 2 * size + 1; i++) { 283 smdata->kernel->data.F32[i] /= sum; 284 } 285 286 return true; 287 } 288 289 psImageSmoothCacheData *psImageSmoothCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) { 290 291 psAssert (modelPSF, "psf model must be defined"); 292 293 psEllipseAxes axes; 294 bool useReff = pmModelUseReff (modelPSF->type); 295 psF32 *PAR = modelPSF->params->data.F32; 296 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff); 297 298 *sigma = NAN; 299 *kappa = NAN; 300 301 // XXX need to do this more carefully 302 if (modelPSF->type == modelType_GAUSS) { 303 float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]); 304 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 305 *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35; 306 } 307 if (modelPSF->type == modelType_PS1_V1) { 308 *sigma = 0.5 * (axes.major + axes.minor); 309 *kappa = PAR[PM_PAR_7]; 310 } 311 psAssert (isfinite(*sigma), "invalid model type"); 312 313 // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector 314 psImageSmoothCacheData *smdata = psImageSmoothCacheAlloc (flux, *sigma, nsigma); 315 316 if (modelPSF->type == modelType_GAUSS) { 317 psImageSmoothCacheKernel_Gauss (smdata, *sigma); 318 } 319 if (modelPSF->type == modelType_PS1_V1) { 320 psImageSmoothCacheKernel_PS1_V1 (smdata, *sigma, *kappa); 321 } 322 323 return smdata; 324 } 325 326 psImageSmooth2dCacheData *psImageSmooth2dCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) { 327 328 psAssert (modelPSF, "psf model must be defined"); 329 330 psEllipseAxes axes; 331 bool useReff = pmModelUseReff (modelPSF->type); 332 psF32 *PAR = modelPSF->params->data.F32; 333 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff); 334 335 *sigma = NAN; 336 *kappa = NAN; 337 338 // XXX need to do this more carefully 339 if (modelPSF->type == modelType_GAUSS) { 340 float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]); 341 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 342 *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35; 343 } 344 if (modelPSF->type == modelType_PS1_V1) { 345 *sigma = 0.5 * (axes.major + axes.minor); 346 *kappa = PAR[PM_PAR_7]; 347 } 348 psAssert (isfinite(*sigma), "invalid model type"); 349 350 // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector 351 psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheAlloc (nsigma); 352 353 if (modelPSF->type == modelType_GAUSS) { 354 psImageSmooth2dCacheKernel_Gauss (smdata, *sigma); 355 } 356 if (modelPSF->type == modelType_PS1_V1) { 357 psImageSmooth2dCacheKernel_PS1_V1 (smdata, *sigma, *kappa); 358 } 359 360 return smdata; 361 } 362 250 363 pmPCMdata *pmPCMinit(pmSource *source, pmSourceFitOptions *fitOptions, pmModel *model, psImageMaskType maskVal, float psfSize) { 251 364 252 // make sure we save a cached copy of the psf flux 253 pmSourceCachePSF (source, maskVal); 254 255 // convert the cached cached psf model for this source to a psKernel 256 psKernel *psf = pmPCMkernelFromPSF (source, psfSize); 257 if (!psf) { 258 // NOTE: this only happens if the source is too close to an edge 259 model->flags |= PM_MODEL_STATUS_BADARGS; 260 return NULL; 261 } 262 263 # if (USE_DELTA_PSF) 264 psImageInit (psf->image, 0.0); 265 psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0; 266 # endif 365 modelType_GAUSS = pmModelClassGetType ("PS_MODEL_GAUSS"); 366 modelType_PS1_V1 = pmModelClassGetType ("PS_MODEL_PS1_V1"); 267 367 268 368 // count the number of unmasked pixels: … … 298 398 if (nPix < nParams + 1) { 299 399 psTrace ("psModules.objects", 4, "insufficient valid pixels\n"); 300 psFree (psf);301 400 psFree (constraint); 302 401 model->flags |= PM_MODEL_STATUS_BADARGS; … … 306 405 // generate PCM data storage structure 307 406 pmPCMdata *pcm = pmPCMdataAlloc (params, constraint->paramMask, source); 308 309 pcm->psf = psf;310 407 pcm->modelConv = psMemIncrRefCounter(model); 311 408 pcm->constraint = constraint; 409 410 pcm->poissonErrors = fitOptions->poissonErrors; 411 pcm->nsigma = fitOptions->nsigma; 312 412 313 413 pcm->nPix = nPix; … … 316 416 317 417 # if (USE_1D_GAUSS) 318 pmModel *modelPSF = source->modelPSF;319 psAssert (modelPSF, "psf model must be defined");320 321 psEllipseAxes axes;322 bool useReff = pmModelUseReff (modelPSF->type);323 psF32 *PAR = modelPSF->params->data.F32;324 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);325 326 float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);327 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);328 418 329 419 pcm->use1Dgauss = true; 330 pcm->sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35; 331 pcm->nsigma = 2.0; 332 333 pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma); 420 if (USE_1D_CACHE) { 421 pcm->smdata = psImageSmoothCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF); 422 } else { 423 pcm->smdata2d = psImageSmooth2dCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF); 424 } 425 334 426 # else 427 // make sure we save a cached copy of the psf flux 428 pmSourceCachePSF (source, maskVal); 429 430 // convert the cached cached psf model for this source to a psKernel 431 psKernel *psf = pmPCMkernelFromPSF (source, psfSize); 432 if (!psf) { 433 // NOTE: this only happens if the source is too close to an edge 434 model->flags |= PM_MODEL_STATUS_BADARGS; 435 return NULL; 436 } 437 438 # if (USE_DELTA_PSF) 439 psImageInit (psf->image, 0.0); 440 psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0; 441 # endif 442 pcm->psf = psf; 335 443 pcm->smdata = NULL; 336 444 # endif … … 395 503 pcm->dmodelsConvFlux->data[n] = psImageCopy (pcm->dmodelsConvFlux->data[n], source->pixels, PS_TYPE_F32); 396 504 } 397 psFree(pcm->smdata); 398 pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma); 505 506 // If we have changed the window, we need to redefine the smoothing target vectors (but pcm->sigma,kappa,nsigma remain) 507 if (USE_1D_CACHE) { 508 psFree(pcm->smdata); 509 pcm->smdata = psImageSmoothCacheAlloc (source->pixels, pcm->sigma, pcm->nsigma); 510 511 pmModel *modelPSF = source->modelPSF; 512 if (modelPSF->type == modelType_GAUSS) { 513 psImageSmoothCacheKernel_Gauss (pcm->smdata, pcm->sigma); 514 } 515 if (modelPSF->type == modelType_PS1_V1) { 516 psImageSmoothCacheKernel_PS1_V1 (pcm->smdata, pcm->sigma, pcm->kappa); 517 } 518 } else { 519 psFree(pcm->smdata2d); 520 pcm->smdata2d = psImageSmooth2dCacheAlloc (pcm->nsigma); 521 522 pmModel *modelPSF = source->modelPSF; 523 if (modelPSF->type == modelType_GAUSS) { 524 // psImageSmooth2dCacheKernel_Gauss (pcm->smdata2d, pcm->sigma); 525 } 526 if (modelPSF->type == modelType_PS1_V1) { 527 psImageSmooth2dCacheKernel_PS1_V1 (pcm->smdata2d, pcm->sigma, pcm->kappa); 528 } 529 } 399 530 } 400 531 … … 403 534 404 535 // construct a realization of the source model 405 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize ) {536 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma) { 406 537 407 538 PS_ASSERT_PTR_NON_NULL(source, false); … … 420 551 // convolve the model image with the PSF 421 552 if (USE_1D_GAUSS) { 422 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):423 // * the model flux is not masked424 // * threading takes place above this level425 553 426 // define the Gauss parameters from the psf 427 pmModel *modelPSF = source->modelPSF; 428 psAssert (modelPSF, "psf model must be defined"); 429 430 psEllipseAxes axes; 431 bool useReff = pmModelUseReff (modelPSF->type); 432 psF32 *PAR = modelPSF->params->data.F32; 433 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff); 434 435 float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]); 436 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 437 438 float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35; 439 float nsigma = 2.0; 440 441 psImageSmooth (source->modelFlux, sigma, nsigma); 554 float sigma = NAN; 555 float kappa = NAN; 556 557 if (USE_1D_CACHE) { 558 psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF); 559 psImageSmoothCache_F32 (source->modelFlux, smdata); 560 psFree (smdata); 561 } else { 562 psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF); 563 psImageSmooth2dCache_F32 (source->modelFlux, smdata); 564 psFree (smdata); 565 } 566 // old call: psImageSmooth (source->modelFlux, sigma, nsigma); 442 567 } else { 443 568 // make sure we save a cached copy of the psf flux … … 459 584 460 585 // construct a realization of the source model 461 bool pmPCMMakeModel (pmSource *source, pmModel *model, psImageMaskType maskVal, int psfSize) {586 bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize) { 462 587 463 588 PS_ASSERT_PTR_NON_NULL(source, false); … … 468 593 469 594 // modelFlux always has unity normalization (I0 = 1.0) 470 pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal); 595 // pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal); 596 pmModelAdd (source->modelFlux, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_SKY | PM_MODEL_OP_NORM, maskVal); 471 597 472 598 // convolve the model image with the PSF 473 599 if (USE_1D_GAUSS) { 474 // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread): 475 // * the model flux is not masked 476 // * threading takes place above this level 477 478 // define the Gauss parameters from the psf 479 pmModel *modelPSF = source->modelPSF; 480 psAssert (modelPSF, "psf model must be defined"); 481 482 psEllipseAxes axes; 483 bool useReff = pmModelUseReff (modelPSF->type); 484 psF32 *PAR = modelPSF->params->data.F32; 485 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff); 486 487 float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]); 488 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 489 490 float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35; 491 float nsigma = 2.0; 492 493 psImageSmooth (source->modelFlux, sigma, nsigma); 600 601 float sigma = NAN; 602 float kappa = NAN; 603 604 if (USE_1D_CACHE) { 605 psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF); 606 psImageSmoothCache_F32 (source->modelFlux, smdata); 607 psFree (smdata); 608 } else { 609 psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF); 610 psImageSmooth2dCache_F32 (source->modelFlux, smdata); 611 psFree (smdata); 612 } 613 // old call: psImageSmooth (source->modelFlux, sigma, nsigma); 494 614 } else { 495 615 // make sure we save a cached copy of the psf flux … … 509 629 return true; 510 630 } 511 -
trunk/psModules/src/objects/pmPCMdata.h
r36085 r36375 14 14 /// @addtogroup Objects Object Detection / Analysis Functions 15 15 /// @{ 16 17 // XXX this is basically for testing -- when I am happy with the convolution process, I'll strip this out 18 # define USE_1D_CACHE 0 19 # define USE_1D_GAUSS 1 16 20 17 21 /** pmPCMdata : PSF Convolved Model data storage structure … … 36 40 int nDOF; 37 41 42 bool poissonErrors; 43 38 44 bool use1Dgauss; 45 float kappa; 39 46 float sigma; 40 47 float nsigma; 41 48 42 psImageSmooth_PreAlloc_Data *smdata; 49 // psArray *smdata; 50 psImageSmoothCacheData *smdata; 51 psImageSmooth2dCacheData *smdata2d; 43 52 } pmPCMdata; 44 53 … … 96 105 bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize); 97 106 98 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize );107 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma); 99 108 100 bool pmPCMMakeModel (pmSource *source, pmModel *model, psImageMaskType maskVal, int psfSize);109 bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize); 101 110 102 111 /// @} -
trunk/psModules/src/objects/pmSource.c
r35768 r36375 66 66 psFree(tmp->extpars); 67 67 psFree(tmp->diffStats); 68 psFree(tmp->galaxyFits); 68 69 psFree(tmp->radialAper); 69 70 psTrace("psModules.objects", 10, "---- end ----\n"); … … 164 165 source->extpars = NULL; 165 166 source->diffStats = NULL; 167 source->galaxyFits = NULL; 166 168 source->radialAper = NULL; 167 169 source->parent = NULL; … … 690 692 // why do we recalculate moments here? 691 693 // we already attempt to do this in psphotSourceStats 692 // pmSourceMoments (source, INNER_RADIUS);693 694 Nsatstar ++; 694 695 continue; … … 804 805 return true; 805 806 } 806 807 /******************************************************************************808 pmSourceMoments(source, radius): this function takes a subImage defined in the809 pmSource data structure, along with the peak location, and determines the810 various moments associated with that peak.811 812 Requires the following to have been created:813 pmSource814 pmSource->peak815 pmSource->pixels816 pmSource->variance817 pmSource->mask818 819 XXX: The peak calculations are done in image coords, not subImage coords.820 821 XXX EAM : this version clips input pixels on S/N822 XXX EAM : this version returns false for several reasons823 *****************************************************************************/824 # define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)825 826 /*** this been moved to pmSourceMoments.c ***/827 # if (0)828 bool pmSourceMoments(pmSource *source,829 psF32 radius)830 {831 psTrace("psModules.objects", 10, "---- begin ----\n");832 PS_ASSERT_PTR_NON_NULL(source, false);833 PS_ASSERT_PTR_NON_NULL(source->peak, false);834 PS_ASSERT_PTR_NON_NULL(source->pixels, false);835 PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);836 837 //838 // XXX: Verify the setting for sky if source->moments == NULL.839 //840 psF32 sky = 0.0;841 if (source->moments == NULL) {842 source->moments = pmMomentsAlloc();843 } else {844 sky = source->moments->Sky;845 }846 847 //848 // Sum = SUM (z - sky)849 // X1 = SUM (x - xc)*(z - sky)850 // X2 = SUM (x - xc)^2 * (z - sky)851 // XY = SUM (x - xc)*(y - yc)*(z - sky)852 //853 psF32 peakPixel = -PS_MAX_F32;854 psS32 numPixels = 0;855 psF32 Sum = 0.0;856 psF32 Var = 0.0;857 psF32 X1 = 0.0;858 psF32 Y1 = 0.0;859 psF32 X2 = 0.0;860 psF32 Y2 = 0.0;861 psF32 XY = 0.0;862 psF32 x = 0;863 psF32 y = 0;864 psF32 R2 = PS_SQR(radius);865 866 psF32 xPeak = source->peak->x;867 psF32 yPeak = source->peak->y;868 psF32 xOff = source->pixels->col0 - source->peak->x;869 psF32 yOff = source->pixels->row0 - source->peak->y;870 871 // XXX why do I get different results for these two methods of finding Sx?872 // XXX Sx, Sy would be better measured if we clip pixels close to sky873 // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?874 // We loop through all pixels in this subimage (source->pixels), and for each875 // pixel that is not masked, AND within the radius of the peak pixel, we876 // proceed with the moments calculation. need to do two loops for a877 // numerically stable result. first loop: get the sums.878 // XXX EAM : mask == 0 is valid879 880 for (psS32 row = 0; row < source->pixels->numRows ; row++) {881 882 psF32 *vPix = source->pixels->data.F32[row];883 psF32 *vWgt = source->variance->data.F32[row];884 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];885 886 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {887 if (vMsk) {888 if (*vMsk) {889 vMsk++;890 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to mask: %d\n",891 col, row, (int)*vMsk);892 continue;893 }894 vMsk++;895 }896 if (isnan(*vPix)) continue;897 898 psF32 xDiff = col + xOff;899 psF32 yDiff = row + yOff;900 901 // radius is just a function of (xDiff, yDiff)902 if (!VALID_RADIUS(xDiff, yDiff, R2)) {903 #if 1904 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to position: %f %f\n",905 col, row, xDiff, yDiff);906 #endif907 continue;908 }909 910 psF32 pDiff = *vPix - sky;911 psF32 wDiff = *vWgt;912 913 // XXX EAM : check for valid S/N in pixel914 // XXX EAM : should this limit be user-defined?915 #if 1916 if (PS_SQR(pDiff) < wDiff) {917 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to insignificance: %f, %f\n",918 col, row, pDiff, wDiff);919 continue;920 }921 #endif922 923 Var += wDiff;924 Sum += pDiff;925 926 psF32 xWght = xDiff * pDiff;927 psF32 yWght = yDiff * pDiff;928 929 X1 += xWght;930 Y1 += yWght;931 932 XY += xDiff * yWght;933 X2 += xDiff * xWght;934 Y2 += yDiff * yWght;935 936 peakPixel = PS_MAX (*vPix, peakPixel);937 numPixels++;938 }939 }940 941 // if we have less than (1/4) of the possible pixels, force a retry942 // XXX EAM - the limit is a bit arbitrary. make it user defined?943 if ((numPixels < 0.75*R2) || (Sum <= 0)) {944 psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n",945 numPixels, (int)(0.75*R2), Sum);946 psTrace("psModules.objects", 10, "---- end (false) ----\n");947 return (false);948 }949 950 psTrace ("psModules.objects", 4, "sky: %f Sum: %f X1: %f Y1: %f X2: %f Y2: %f XY: %f Npix: %d\n",951 sky, Sum, X1, Y1, X2, Y2, XY, numPixels);952 953 //954 // first moment X = X1/Sum + xc955 // second moment X = sqrt (X2/Sum - (X1/Sum)^2)956 // Sxy = XY / Sum957 //958 x = X1/Sum;959 y = Y1/Sum;960 if ((fabs(x) > radius) || (fabs(y) > radius)) {961 psTrace ("psModules.objects", 3, "large centroid swing; invalid peak %d, %d\n",962 source->peak->x, source->peak->y);963 psTrace("psModules.objects", 10, "---- end(false) ----\n");964 return (false);965 }966 967 source->moments->Mx = x + xPeak;968 source->moments->My = y + yPeak;969 970 // XXX EAM : Sxy needs to have x*y subtracted971 source->moments->Mxy = XY/Sum - x*y;972 source->moments->Sum = Sum;973 source->moments->SN = Sum / sqrt(Var);974 source->moments->Peak = peakPixel;975 source->moments->nPixels = numPixels;976 977 // XXX EAM : these values can be negative, so we need to limit the range978 // XXX EAM : make the use of this consistent: should this be the second moment or sqrt?979 // source->moments->Mxx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));980 // source->moments->Myy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));981 source->moments->Mxx = PS_MAX(X2/Sum - PS_SQR(x), 0);982 source->moments->Myy = PS_MAX(Y2/Sum - PS_SQR(y), 0);983 984 psTrace ("psModules.objects", 4,985 "sky: %f Sum: %f Mx: %f My: %f Mxx: %f Myy: %f Mxy: %f\n",986 sky, Sum, source->moments->Mx, source->moments->My,987 source->moments->Mxx, source->moments->Myy, source->moments->Mxy);988 989 psTrace("psModules.objects", 10, "---- end ----\n");990 return(true);991 }992 # endif993 807 994 808 // construct a realization of the source model -
trunk/psModules/src/objects/pmSource.h
r34403 r36375 40 40 PM_SOURCE_TMPF_PETRO_KEEP = 0x0100, 41 41 PM_SOURCE_TMPF_PETRO_SKIP = 0x0200, 42 PM_SOURCE_TMPF_EXT_FIT = 0x0400, // not just galaxies (trails as well) 43 PM_SOURCE_TMPF_PETRO = 0x0800, 42 44 } pmSourceTmpF; 43 45 … … 117 119 pmSourceExtendedPars *extpars; ///< extended source parameters 118 120 pmSourceDiffStats *diffStats; ///< extra parameters for difference detections 121 pmSourceGalaxyFits *galaxyFits; ///< fits to galaxy models (psphotFullForce only) 119 122 psArray *radialAper; ///< radial flux in circular apertures 120 123 pmSource *parent; ///< reference to the master source from which this is derived -
trunk/psModules/src/objects/pmSourceExtendedPars.c
r34403 r36375 286 286 return pars; 287 287 } 288 289 // *** pmSourceExtFitPars describes extra metadata related to an extended fit 290 static void pmSourceGalaxyFitsFree (pmSourceGalaxyFits *tmp) { 291 292 psFree (tmp->Flux); 293 psFree (tmp->dFlux); 294 psFree (tmp->chisq); 295 296 return; 297 } 298 299 pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void) { 300 301 pmSourceGalaxyFits *tmp = (pmSourceGalaxyFits *) psAlloc(sizeof(pmSourceGalaxyFits)); 302 psMemSetDeallocator(tmp, (psFreeFunc) pmSourceGalaxyFitsFree); 303 304 tmp->Flux = psVectorAllocEmpty (25, PS_TYPE_F32); 305 tmp->dFlux = psVectorAllocEmpty (25, PS_TYPE_F32); 306 tmp->chisq = psVectorAllocEmpty (25, PS_TYPE_F32); 307 tmp->nPix = 0; 308 309 return tmp; 310 } -
trunk/psModules/src/objects/pmSourceExtendedPars.h
r32347 r36375 82 82 } pmSourceExtFitPars; 83 83 84 typedef struct { 85 psVector *Flux; 86 psVector *dFlux; 87 psVector *chisq; 88 int nPix; 89 } pmSourceGalaxyFits; 90 84 91 pmSourceRadialFlux *pmSourceRadialFluxAlloc(); 85 92 bool psMemCheckSourceRadialFlux(psPtr ptr); … … 109 116 pmSourceExtFitPars *pmSourceExtFitParsAlloc (void); 110 117 118 pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void); 119 120 111 121 /// @} 112 122 # endif /* PM_SOURCE_H */ -
trunk/psModules/src/objects/pmSourceFitModel.c
r36085 r36375 59 59 opt->maxTol = 1.00; 60 60 opt->weight = 1.00; 61 opt->nsigma = 5.00; 61 62 opt->maxChisqDOF = NAN; 62 63 opt->poissonErrors = true; … … 281 282 // set the model success or failure status 282 283 model->flags |= PM_MODEL_STATUS_FITTED; 283 if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE; 284 if (!fitStatus) { 285 if (isnan(myMin->value)) { 286 model->flags |= PM_MODEL_STATUS_NAN_CHISQ; 287 } else { 288 model->flags |= PM_MODEL_STATUS_NONCONVERGE; 289 } 290 } 284 291 285 292 if (myMin->chisqConvergence) { -
trunk/psModules/src/objects/pmSourceFitModel.h
r36085 r36375 34 34 float weight; ///< use this weight for constant-weight fits 35 35 float covarFactor; ///< covariance factor for calculating the chisq 36 float nsigma; ///< how far out to convolve 36 37 bool poissonErrors; ///< use poisson errors for fits? 37 38 bool saveCovariance; -
trunk/psModules/src/objects/pmSourceFitPCM.c
r36085 r36375 51 51 # define TIMING 0 52 52 53 bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal); 54 53 55 bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) { 54 56 … … 113 115 } else { 114 116 // xxx this is wrong because it does not convolve with the psf 115 pmSourceChisqUnsubtracted (source, pcm->modelConv, maskVal); 117 pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize); 118 pmSourceChisqModelFlux (source, pcm->modelConv, maskVal); 116 119 } 117 120 if (TIMING) { t4 = psTimerMark ("pmSourceFitPCM"); } … … 119 122 // set the model success or failure status 120 123 pcm->modelConv->flags |= PM_MODEL_STATUS_FITTED; 121 if (!fitStatus) pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE; 124 125 if (!fitStatus) { 126 if (isnan(myMin->value)) { 127 pcm->modelConv->flags |= PM_MODEL_STATUS_NAN_CHISQ; 128 } else { 129 pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE; 130 } 131 } 122 132 123 133 if (myMin->chisqConvergence) { -
trunk/psModules/src/objects/pmSourceFitSet.c
r36085 r36375 352 352 // set the model success or failure status 353 353 model->flags |= PM_MODEL_STATUS_FITTED; 354 if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE; 354 if (!fitStatus) { 355 if (isnan(myMin->value)) { 356 model->flags |= PM_MODEL_STATUS_NAN_CHISQ; 357 } else { 358 model->flags |= PM_MODEL_STATUS_NONCONVERGE; 359 } 360 } 355 361 356 362 // models can go insane: reject these -
trunk/psModules/src/objects/pmSourceIO.c
r35610 r36375 69 69 psString *xfitname, // Extension name for extended fitted measurements 70 70 psString *xradname, // Extension name for radial apertures 71 psString *xgalname, // Extension name for galaxy shapes 71 72 const pmFPAfile *file, // File of interest 72 73 const pmFPAview *view // View to level of interest … … 140 141 } 141 142 *xradname = pmFPAfileNameFromRule (rule, file, view); 143 } 144 145 // EXTNAME for radial apertures 146 if (xgalname) { 147 const char *rule = psMetadataLookupStr(&status, menu, "CMF.XGAL"); 148 if (!rule) { 149 psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XGAL in EXTNAME.RULES in camera.config"); 150 return false; 151 } 152 *xgalname = pmFPAfileNameFromRule (rule, file, view); 142 153 } 143 154 … … 362 373 status &= pmSourcesWrite_##TYPE##_XRAD (file->fits, readout, sources, file->header, xradname, recipe); \ 363 374 } \ 375 if (xgalname) { \ 376 status &= pmSourcesWrite_##TYPE##_XGAL (file->fits, sources, xgalname, recipe); \ 377 } \ 364 378 } 365 379 … … 464 478 } 465 479 466 // if this is not TRUE, the output files only contain the psf measurements. 467 bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS"); 480 // if none of these are TRUE, the output files only contain the psf measurements. 481 bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN"); 482 bool doAnnuli = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI"); 483 bool XSRC_OUTPUT = doPetrosian || doAnnuli; 468 484 bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS"); 469 485 bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES"); 486 bool XGAL_OUTPUT = psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES"); 470 487 471 488 // define the EXTNAME values for the different data segments: … … 476 493 psString xfitname = NULL; 477 494 psString xradname = NULL; 495 psString xgalname = NULL; 478 496 if (!pmSourceIOextnames(&headname, &dataname, &deteffname, 479 497 XSRC_OUTPUT ? &xsrcname : NULL, 480 498 XFIT_OUTPUT ? &xfitname : NULL, 481 499 XRAD_OUTPUT ? &xradname : NULL, 500 XGAL_OUTPUT ? &xgalname : NULL, 482 501 file, view)) { 483 502 return false; … … 563 582 psMetadataAddStr (outhead, PS_LIST_TAIL, "XRADNAME", PS_META_REPLACE, "name of XRAD table extension", xradname); 564 583 } 584 if (xgalname) { 585 psMetadataAddStr (outhead, PS_LIST_TAIL, "XGALNAME", PS_META_REPLACE, "name of XGAL table extension", xgalname); 586 } 565 587 566 588 // these are case-sensitive since the EXTYPE is case-sensitive … … 609 631 psFree (xfitname); 610 632 psFree (xradname); 633 psFree (xgalname); 611 634 psFree (deteffname); 612 635 … … 620 643 psFree (xfitname); 621 644 psFree (xradname); 645 psFree (xgalname); 622 646 psFree (deteffname); 623 647 return false; 624 648 649 case PM_FPA_FILE_CFF: { 650 // determine the output table format 651 psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT"); 652 if (!status) { 653 psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data"); 654 return false; 655 } 656 657 hdu = pmFPAviewThisHDU (view, fpa); 658 pmConfigConformHeader(hdu->header, file->format); 659 psFitsWriteBlank (file->fits, hdu->header, NULL); 660 file->header = hdu->header; 661 file->wrote_phu = true; 662 if (!pmSourcesWrite_CFF(readout, file->fits, sources, hdu->header, recipe)) { 663 psError(PS_ERR_UNKNOWN, false, "failed to write CFF"); 664 return false; 665 } 666 break; 667 } 668 625 669 default: 626 670 fprintf (stderr, "warning: type mismatch\n"); … … 914 958 psArray *sources = NULL; 915 959 pmHDU *hdu; 960 961 // define the EXTNAME values for the different data segments: 962 psString headname = NULL; 963 psString dataname = NULL; 964 psString deteffname = NULL; 965 psString xsrcname = NULL; 966 psString xfitname = NULL; 967 psString xradname = NULL; 968 psString xgalname = NULL; 969 970 psMetadata *tableHeader = NULL; 971 char *xtension = NULL; 916 972 917 973 switch (file->type) { … … 963 1019 hdu = pmFPAviewThisHDU (view, file->fpa); 964 1020 965 // define the EXTNAME values for the different data segments:966 psString headname = NULL;967 psString dataname = NULL;968 psString deteffname = NULL;969 psString xsrcname = NULL;970 psString xfitname = NULL;971 psString xradname = NULL;972 973 1021 // determine the output table format. Assume if we need to output extendend source 974 1022 // parameters that they may exist in the input. … … 981 1029 } 982 1030 983 // if this is not TRUE, the output files only contain the psf measurements. 984 bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS"); 1031 // if none of these are TRUE, we only read the psf measurements 1032 // XXX: shouldn't we look for these extensions and read the regardless of the recipe values? 1033 bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN"); 1034 bool doAnnuli = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI"); 1035 bool XSRC_OUTPUT = doPetrosian || doAnnuli; 985 1036 bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS"); 986 1037 bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES"); 1038 bool XGAL_OUTPUT = false; // psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES"); 987 1039 988 1040 if (!pmSourceIOextnames(&headname, &dataname, &deteffname, … … 990 1042 XFIT_OUTPUT ? &xfitname : NULL, 991 1043 XRAD_OUTPUT ? &xradname : NULL, 1044 XGAL_OUTPUT ? &xgalname : NULL, 992 1045 file, view)) { 993 1046 return false; … … 1033 1086 } 1034 1087 1035 psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header1088 tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header 1036 1089 if (!tableHeader) psAbort("cannot read table header"); 1037 1090 1038 char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");1091 xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION"); 1039 1092 if (!xtension) psAbort("cannot read table type"); 1040 1093 if (strcmp (xtension, "BINTABLE")) { … … 1132 1185 break; 1133 1186 1187 case PM_FPA_FILE_CFF: 1188 // read in header, if not yet loaded 1189 hdu = pmFPAviewThisHDU (view, file->fpa); 1190 1191 // look these up in the camera config? 1192 // headrule = {CHIP.NAME}.hdr 1193 // datarule = {CHIP.NAME}.cff 1194 1195 // define the EXTNAME values for the different data segments: 1196 headname = pmFPAfileNameFromRule("{CHIP.NAME}.hdr", file, view); 1197 dataname = pmFPAfileNameFromRule("{CHIP.NAME}.cff", file, view); 1198 1199 // advance to the IMAGE HEADER extension 1200 if (hdu->header == NULL) { 1201 // if the IMAGE header does not exist, we have no data for this view 1202 if (!psFitsMoveExtNameClean (file->fits, headname)) { 1203 readout->data_exists = false; 1204 psFree (headname); 1205 psFree (dataname); 1206 return true; 1207 } 1208 hdu->header = psFitsReadHeader (NULL, file->fits); 1209 } 1210 1211 // advance to the table data extension 1212 // since we have read the IMAGE header, the TABLE header should exist 1213 if (!psFitsMoveExtName (file->fits, dataname)) { 1214 psAbort("cannot find data extension %s in %s", dataname, file->filename); 1215 } 1216 1217 tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header 1218 if (!tableHeader) psAbort("cannot read table header"); 1219 1220 // verify this is a binary table 1221 char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION"); 1222 if (!xtension) psAbort("cannot read table type"); 1223 if (strcmp (xtension, "BINTABLE")) { 1224 psWarning ("no binary table in extension %s, skipping\n", dataname); 1225 psFree(tableHeader); 1226 return false; 1227 } 1228 1229 sources = pmSourcesRead_CFF(file->fits, hdu->header); 1230 1231 psTrace("psModules.objects", 6, "read CMF table from %s : %s : %s", file->filename, headname, dataname); 1232 psFree (headname); 1233 psFree (dataname); 1234 psFree (tableHeader); 1235 break; 1236 1134 1237 default: 1135 1238 fprintf (stderr, "warning: type mismatch\n"); -
trunk/psModules/src/objects/pmSourceIO.h
r35610 r36375 21 21 bool pmSourcesWrite_##TYPE##_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); \ 22 22 bool pmSourcesWrite_##TYPE##_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); \ 23 bool pmSourcesWrite_##TYPE##_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe); \ 23 24 psArray *pmSourcesRead_##TYPE (psFits *fits, psMetadata *header); \ 24 25 bool pmSourcesRead_##TYPE##_XSRC (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index); \ … … 52 53 53 54 psArray *pmSourcesReadCMP (char *filename, psMetadata *header); 55 psArray *pmSourcesRead_CFF (psFits *fits, psMetadata *header); 56 bool pmSourcesWrite_CFF (pmReadout *readout, psFits *fits, psArray *sources, psMetadata *header, psMetadata *recipe); 54 57 55 58 bool pmSourcesWritePSFs (psArray *sources, char *filename); -
trunk/psModules/src/objects/pmSourceIO_CMF.c.in
r35768 r36375 789 789 char name[64]; 790 790 791 pmModelType modelTypeTrail = pmModelClassGetType("PS_MODEL_TRAIL"); 792 791 793 // create a header to hold the output data 792 794 psMetadata *outhead = psMetadataAlloc (); … … 798 800 sources = psArraySort (sources, pmSourceSortByFlux); 799 801 800 @>PS1_DV2@float magOffset;801 @>PS1_DV2@float zeroptErr;802 @>PS1_DV2@float fwhmMajor;803 @>PS1_DV2@float fwhmMinor;804 @>PS1_DV2@pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);802 float magOffset; 803 float zeroptErr; 804 float fwhmMajor; 805 float fwhmMinor; 806 pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader); 805 807 806 808 // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams … … 823 825 @>PS1_DV2@ pmChip *chip = readout->parent->parent; 824 826 827 pmModelStatus badModel = PM_MODEL_STATUS_NONE; 828 badModel |= PM_MODEL_STATUS_BADARGS; 829 badModel |= PM_MODEL_STATUS_OFFIMAGE; 830 badModel |= PM_MODEL_STATUS_NAN_CHISQ; 831 badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS; 832 badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID; 833 badModel |= PM_MODEL_PCM_FAIL_GUESS; 834 825 835 table = psArrayAllocEmpty (sources->n); 826 836 … … 847 857 848 858 // skip models which were not actually fitted 849 if (model->flags & PM_MODEL_STATUS_BADARGS) continue; 859 // XXX 860 if (model->flags & badModel) continue; 850 861 851 862 PAR = model->params->data.F32; … … 853 864 xPos = PAR[PM_PAR_XPOS]; 854 865 yPos = PAR[PM_PAR_YPOS]; 855 xErr = dPAR[PM_PAR_XPOS]; 856 yErr = dPAR[PM_PAR_YPOS]; 866 867 // for the extended source models, we do not always fit the centroid in the non-linear fitting process 868 // current situation (hard-wired into psphotSourceFits.c:psphotFitPCM, 869 // SERSIC, DEV, EXP : X,Y not fitted (PCM and not PCM) 870 // TRAIL : X,Y are fitted 871 // 872 873 // XXX this should be based on what happened, not on the model type 874 if (model->type == modelTypeTrail) { 875 xErr = dPAR[PM_PAR_XPOS]; 876 yErr = dPAR[PM_PAR_YPOS]; 877 } else { 878 // this is definitely an underestimate since it does not 879 // account for the extent of the source 880 xErr = fwhmMajor * model->magErr / 2.35; 881 yErr = fwhmMinor * model->magErr / 2.35; 882 } 857 883 858 884 @>PS1_DV2@ psSphere ptSky = {0.0, 0.0, 0.0, 0.0}; … … 870 896 row = psMetadataAlloc (); 871 897 872 // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)873 898 // the psMetadataAdd entry and the double quotes are used by grep to select the output fields for automatic documentation 874 899 // This set of psMetadataAdd Entries marks the "----" "Start of the XFIT segment" … … 888 913 @>PS1_DV2@ float calMag = isfinite(magOffset) ? model->mag + magOffset : NAN; 889 914 @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CAL_MAG", PS_DATA_F32, "EXT Magnitude using supplied calibration", calMag); 890 @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ", PS_DATA_F32, "EXT Magnitude using supplied calibration", model->chisq); 891 @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF", PS_DATA_S32, "EXT Magnitude using supplied calibration", model->nDOF); 915 @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ", PS_DATA_F32, "EXT Model Chisq", model->chisq); 916 @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF", PS_DATA_S32, "EXT Model num degrees of freedom", model->nDOF); 917 @>PS1_SV1,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_MODEL_TYPE", PS_DATA_S32, "type for chosen EXT_MODEL", source->modelEXT ? source->modelEXT->type : -1); 918 919 // EAM : adding for PV2 outputs: 920 @>PS1_SV1@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_FLAGS", PS_DATA_S16, "model fit flags (pmModelStatus)", source->modelEXT ? source->modelEXT->flags : 0); 892 921 893 922 @>PS1_DV2@ psMetadataAddF32 (row, PS_LIST_TAIL, "POSANGLE", 0, "position angle at source (degrees)", posAngle); … … 946 975 947 976 snprintf (name, 64, "EXT_PAR_%02d", k); 948 977 949 978 if (k < model->params->n) { 950 979 psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", model->params->data.F32[k]); … … 956 985 // optionally, write out the covariance matrix values 957 986 // XXX do I need to pad this to match the biggest covar matrix? 958 if ( model->covar) {987 if (false && model->covar) { 959 988 for (int iy = 0; iy < model->covar->numCols; iy++) { 960 989 for (int ix = iy; ix < model->covar->numCols; ix++) { … … 1058 1087 model->magErr = psMetadataLookupF32(&status, row, "EXT_INST_MAG_SIG"); 1059 1088 1089 model->chisq = psMetadataLookupF32(&status, row, "EXT_CHISQ"); 1090 model->nDOF = psMetadataLookupF32(&status, row, "EXT_NDOF"); 1091 1092 // EXT_MODEL_TYPE gives the model chosen by psphot as the best. 1093 // Putting this into the XFIT table makes 3 copies of it (one for each model) 1094 // but since we have many fewer XFIT rows than psf rows that is cheaper than putting it 1095 // in the psf table. 1096 psS32 extModelType = psMetadataLookupS32(&status, row, "EXT_MODEL_TYPE"); 1097 if (!status) { 1098 // older cmfs don't have this column 1099 extModelType = -1; 1100 } 1101 1060 1102 psEllipseAxes axes; 1061 1103 axes.major = psMetadataLookupF32(&status, row, "EXT_WIDTH_MAJ"); … … 1072 1114 if (model->params->n > 7) { 1073 1115 PAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07"); 1074 } 1075 // read the covariance matrix 1076 int nparams = model->params->n; 1077 psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32); 1078 for (int y = 0; y < nparams; y++) { 1079 for (int x = 0; x < nparams; x++) { 1080 char name[64]; 1081 snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x); 1082 covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name); 1116 // XXX add an error: 1117 // dPAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07_"); 1118 } 1119 1120 // XXX : make this depend on what is in the cmf 1121 if (0) { 1122 // read the covariance matrix 1123 int nparams = model->params->n; 1124 psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32); 1125 for (int y = 0; y < nparams; y++) { 1126 for (int x = 0; x < nparams; x++) { 1127 char name[64]; 1128 snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x); 1129 covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name); 1130 } 1131 } 1132 model->covar = covar; 1133 } 1134 1135 if (modelType == extModelType) { 1136 // The software that created this source picked this model as the best of the fits. 1137 // Set the extModel to point to it. 1138 // This is important for programs like psastro (skycal) so that its output cmfs 1139 // will have valid EXT_MODEL_TYPE 1140 psFree(source->modelEXT); 1141 source->modelEXT = psMemIncrRefCounter(model); 1142 source->type = PM_SOURCE_TYPE_EXTENDED; 1143 if (0) { 1144 // since FLAGS were read we don't need to do this 1145 source->mode |= PM_SOURCE_MODE_EXTMODEL; 1146 source->mode |= PM_SOURCE_MODE_NONLINEAR_FIT; 1083 1147 } 1084 1148 } 1085 model->covar = covar;1086 1149 1087 1150 psArrayAdd(source->modelFits, 1, model); 1088 1151 psFree(model); 1089 1090 1152 psFree(row); 1091 1153 } … … 1209 1271 1210 1272 write_annuli: 1211 psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX", PS_DATA_VECTOR, "flux within annuli", radFlux);1212 psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR", PS_DATA_VECTOR, "flux error in annuli", radFluxErr);1213 psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_DATA_VECTOR, "flux standard deviation", radFluxStdev);1214 psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL", PS_DATA_VECTOR, "fill factor of annuli", radFill);1273 psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX", PS_META_REPLACE, "flux within annuli", radFlux); 1274 psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_ERR", PS_META_REPLACE, "flux error in annuli", radFluxErr); 1275 psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_META_REPLACE, "flux standard deviation", radFluxStdev); 1276 psMetadataAddVector (row, PS_LIST_TAIL, "APER_FILL", PS_META_REPLACE, "fill factor of annuli", radFill); 1215 1277 psFree (radFlux); 1216 1278 psFree (radFluxErr); … … 1343 1405 return true; 1344 1406 } 1407 1408 // XXX where should I record the number of columns?? 1409 bool pmSourcesWrite_CMF_@CMFMODE@_XGAL (psFits *fits, psArray *sources, char *extname, psMetadata *recipe) 1410 { 1411 bool status = false; 1412 1413 // perform full non-linear fits / extended source analysis? 1414 if (!psMetadataLookupBool (&status, recipe, "GALAXY_SHAPES")) { 1415 psLogMsg ("psphot", PS_LOG_INFO, "galaxy shapes were not measured, skipping\n"); 1416 return true; 1417 } 1418 1419 // create a header to hold the output data 1420 psMetadata *outhead = psMetadataAlloc (); 1421 1422 // write the links to the image header 1423 psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "galaxy table extension", extname); 1424 1425 // let's write these out in S/N order 1426 sources = psArraySort (sources, pmSourceSortByFlux); 1427 1428 psArray *table = psArrayAllocEmpty (sources->n); 1429 1430 for (int i = 0; i < sources->n; i++) { 1431 1432 pmSource *thisSource = sources->data[i]; 1433 1434 // this is the "real" version of this source 1435 pmSource *source = thisSource->parent ? thisSource->parent : thisSource; 1436 1437 // if we did not fit the galaxy model, modelFits will be NULL 1438 if (source->modelFits == NULL) continue; 1439 1440 // if we did not fit the galaxy model, galaxyFits will also be NULL 1441 if (source->galaxyFits == NULL) continue; 1442 1443 pmModel *model = source->modelFits->data[0]; 1444 if (!model) return false; 1445 1446 // X,Y coordinates are stored with the model parameters 1447 psF32 *PAR = model->params->data.F32; 1448 1449 psMetadata *row = psMetadataAlloc (); 1450 1451 // we write out the x,y positions so people can link to the psf either way (position or ID) 1452 psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET", 0, "IPP detection identifier index", source->seq); 1453 psMetadataAddF32 (row, PS_LIST_TAIL, "X_FIT", 0, "model x coordinate", PAR[PM_PAR_XPOS]); 1454 psMetadataAddF32 (row, PS_LIST_TAIL, "Y_FIT", 0, "model y coordinate", PAR[PM_PAR_YPOS]); 1455 psMetadataAddF32 (row, PS_LIST_TAIL, "NPIX", 0, "number of pixels for fits", source->galaxyFits->nPix); 1456 1457 psVector *Flux = source->galaxyFits->Flux; 1458 psVector *dFlux = source->galaxyFits->dFlux; 1459 psVector *chisq = source->galaxyFits->chisq; 1460 1461 psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX", PS_META_REPLACE, "normalization for galaxy flux", Flux); 1462 psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX_ERR", PS_META_REPLACE, "error on normalization", dFlux); 1463 psMetadataAddVector (row, PS_LIST_TAIL, "GAL_CHISQ", PS_META_REPLACE, "galaxy fit chisq", chisq); 1464 1465 psArrayAdd (table, 100, row); 1466 psFree (row); 1467 } 1468 1469 if (table->n == 0) { 1470 if (!psFitsWriteBlank (fits, outhead, extname)) { 1471 psError(psErrorCodeLast(), false, "Unable to write empty sources file."); 1472 psFree(outhead); 1473 psFree(table); 1474 return false; 1475 } 1476 psFree (outhead); 1477 psFree (table); 1478 return true; 1479 } 1480 1481 psTrace ("pmFPAfile", 5, "writing galaxy data %s\n", extname); 1482 if (!psFitsWriteTable (fits, outhead, table, extname)) { 1483 psError(psErrorCodeLast(), false, "writing galaxy data %s\n", extname); 1484 psFree (outhead); 1485 psFree(table); 1486 return false; 1487 } 1488 psFree (outhead); 1489 psFree (table); 1490 return true; 1491 } 1492 -
trunk/psModules/src/objects/pmSourceIO_PS1_CAL_0.c
r35768 r36375 713 713 return true; 714 714 } 715 716 bool pmSourcesWrite_PS1_CAL_0_XGAL (psFits *fits, psArray *sources, char *extname, psMetadata *recipe) 717 { 718 return true; 719 } -
trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c
r35768 r36375 255 255 return true; 256 256 } 257 258 bool pmSourcesWrite_PS1_DEV_0_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe) 259 { 260 return true; 261 } -
trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c
r35768 r36375 595 595 return true; 596 596 } 597 598 bool pmSourcesWrite_PS1_DEV_1_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe) 599 { 600 return true; 601 } -
trunk/psModules/src/objects/pmSourceIO_SMPDATA.c
r35768 r36375 225 225 return true; 226 226 } 227 228 bool pmSourcesWrite_SMPDATA_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe) 229 { 230 return true; 231 } -
trunk/psModules/src/objects/pmSourceMasks.h
r34403 r36375 56 56 PM_SOURCE_MODE2_DIFF_SELF_MATCH = 0x00000800, ///< positive detection match is probably this source 57 57 PM_SOURCE_MODE2_SATSTAR_PROFILE = 0x00001000, ///< saturated source is modeled with a radial profile 58 59 PM_SOURCE_MODE2_ECONTOUR_FEW_PTS = 0x00002000, ///< too few points to measure the elliptical contour 60 PM_SOURCE_MODE2_RADBIN_NAN_CENTER = 0x00004000, ///< radial bins failed with too many NaN center bin 61 PM_SOURCE_MODE2_PETRO_NAN_CENTER = 0x00008000, ///< petrosian radial bins failed with too many NaN center bin 62 PM_SOURCE_MODE2_PETRO_NO_PROFILE = 0x00010000, ///< petrosian not build because radial bins missing 63 64 PM_SOURCE_MODE2_PETRO_INSIG_RATIO = 0x00020000, ///< insignificant measurement of petrosian ratio 65 PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN = 0x00040000, ///< petrosian ratio in the 0th bin (likely bad) 66 67 PM_SOURCE_MODE2_EXT_FITS_RUN = 0x00080000, ///< we attempted to run extended fits on this source 68 PM_SOURCE_MODE2_EXT_FITS_FAIL = 0x00100000, ///< at least one of the model fits failed 69 PM_SOURCE_MODE2_EXT_FITS_RETRY = 0x00200000, ///< one of the model fits was re-tried with new window 70 PM_SOURCE_MODE2_EXT_FITS_NONE = 0x00400000, ///< ALL of the model fits failed 71 72 58 73 } pmSourceMode2; 59 74 -
trunk/psModules/src/objects/pmSourceMoments.c
r35560 r36375 65 65 void pmSourceMomentsSetVerbose(bool state){ beVerbose = state; } 66 66 67 bool pmSourceMomentsHighOrder (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal); 68 bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal); 69 bool pmSourceMomentsKronFluxes (pmSource *source, float sigma, float minSN, psImageMaskType maskVal); 70 67 71 // if mode & EXTERNAL or mode2 & MATCHED, do not re-calculate the centroid (use peak as centroid) 68 69 72 bool pmSourceMoments(pmSource *source, float radius, float sigma, float minSN, float minKronRadius, psImageMaskType maskVal) 70 73 { … … 74 77 PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false); 75 78 76 // this function assumes the sky has been well-subtracted for the image77 float sky = 0.0;78 79 79 if (source->moments == NULL) { 80 80 source->moments = pmMomentsAlloc(); 81 81 } 82 83 float Sum = 0.0;84 float Var = 0.0;85 float SumCore = 0.0;86 float VarCore = 0.0;87 float R2 = PS_SQR(radius);88 float minSN2 = PS_SQR(minSN);89 float rsigma2 = 0.5 / PS_SQR(sigma);90 82 91 83 // a note about coordinates: coordinates of objects throughout psphot refer to the primary … … 110 102 // of any object drops pretty quickly outside 1-2 sigmas. (The exception is bright 111 103 // saturated stars, for which we need to use a very large radius here) 104 // NOTE: if (mode & EXTERNAL) or (mode2 & MATCHED), do not re-calculate the centroid (use peak as centroid) 105 // (we still call this function because it sets moments->Sum,SN,Peak,nPixels 112 106 if (!pmSourceMomentsGetCentroid (source, 1.5*sigma, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) { 113 107 return false; 114 108 } 115 109 110 pmSourceMomentsHighOrder (source, radius, sigma, minSN, maskVal); 111 112 // now calculate the 1st radial moment (for kron flux) using symmetrical averaging 113 pmSourceMomentsRadialMoment (source, radius, minKronRadius, maskVal); 114 115 // now calculate the kron flux values using the 1st radial moment 116 pmSourceMomentsKronFluxes (source, sigma, minSN, maskVal); 117 118 psTrace ("psModules.objects", 4, "Mrf: %f KronFlux: %f Mxx: %f Mxy: %f Myy: %f Mxxx: %f Mxxy: %f Mxyy: %f Myyy: %f Mxxxx: %f Mxxxy: %f Mxxyy: %f Mxyyy: %f Mxyyy: %f\n", 119 source->moments->Mrf, source->moments->KronFlux, 120 source->moments->Mxx, source->moments->Mxy, source->moments->Myy, 121 source->moments->Mxxx, source->moments->Mxxy, source->moments->Mxyy, source->moments->Myyy, 122 source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy); 123 124 psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f My: %f Sum: %f Mxx: %f Mxy: %f Myy: %f Npix: %d\n", 125 source->peak->xf, source->peak->yf, 126 source->peak->rawFlux, sqrt(source->peak->detValue), 127 source->moments->Mx, source->moments->My, 128 source->moments->Sum, 129 source->moments->Mxx, source->moments->Mxy, source->moments->Myy, 130 source->moments->nPixels); 131 132 return(true); 133 } 134 135 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) { 136 137 // First Pass: calculate the first moments (these are subtracted from the coordinates below) 138 // Sum = SUM (z - sky) 139 // X1 = SUM (x - xc)*(z - sky) 140 // .. etc 141 142 float sky = 0.0; 143 144 float peakPixel = -PS_MAX_F32; 145 psS32 numPixels = 0; 146 float Sum = 0.0; 147 float Var = 0.0; 148 float X1 = 0.0; 149 float Y1 = 0.0; 150 float R2 = PS_SQR(radius); 151 float minSN2 = PS_SQR(minSN); 152 float rsigma2 = 0.5 / PS_SQR(sigma); 153 154 float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage 155 float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage 156 157 // we are guaranteed to have a valid pixel and variance at this location (right? right?) 158 // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]); 159 // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); 160 // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel"); 161 // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel"); 162 163 // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should 164 // not depend on the fractional pixel location of the source. However, the aperture 165 // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel 166 // position of the expected centroid 167 168 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 169 170 float yDiff = row + 0.5 - yPeak; 171 if (fabs(yDiff) > radius) continue; 172 173 float *vPix = source->pixels->data.F32[row]; 174 float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row]; 175 176 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; 177 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row]; 178 179 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) { 180 if (vMsk) { 181 if (*vMsk & maskVal) { 182 vMsk++; 183 continue; 184 } 185 vMsk++; 186 } 187 if (isnan(*vPix)) continue; 188 189 float xDiff = col + 0.5 - xPeak; 190 if (fabs(xDiff) > radius) continue; 191 192 // radius is just a function of (xDiff, yDiff) 193 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 194 if (r2 > R2) continue; 195 196 float pDiff = *vPix - sky; 197 float wDiff = *vWgt; 198 199 // skip pixels below specified significance level. for a PSFs, this 200 // over-weights the wings of bright stars compared to those of faint stars. 201 // for the estimator used for extended source analysis (where the window 202 // function is allowed to be arbitrarily large), we need to clip to avoid 203 // negative second moments. 204 if (PS_SQR(pDiff) < minSN2*wDiff) continue; // 205 if ((minSN > 0.0) && (pDiff < 0)) continue; // 206 207 // Apply a Gaussian window function. Be careful with the window function. S/N 208 // weighting over weights the sky for faint sources 209 if (sigma > 0.0) { 210 float z = r2*rsigma2; 211 assert (z >= 0.0); 212 float weight = exp(-z); 213 214 wDiff *= weight; 215 pDiff *= weight; 216 } 217 218 Var += wDiff; 219 Sum += pDiff; 220 221 float xWght = xDiff * pDiff; 222 float yWght = yDiff * pDiff; 223 224 X1 += xWght; 225 Y1 += yWght; 226 227 peakPixel = PS_MAX (*vPix, peakPixel); 228 numPixels++; 229 } 230 } 231 232 // if we have less than (1/4) of the possible pixels (in circle or box), force a retry 233 int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0); 234 235 // XXX EAM - the limit is a bit arbitrary. make it user defined? 236 if ((numPixels < minPixels) || (Sum <= 0)) { 237 psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum); 238 return (false); 239 } 240 241 // calculate the first moment. 242 float Mx = X1/Sum; 243 float My = Y1/Sum; 244 if ((fabs(Mx) > radius) || (fabs(My) > radius)) { 245 psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y); 246 return (false); 247 } 248 if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) { 249 psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y); 250 } 251 252 psTrace ("psModules.objects", 5, "id: %d, sky: %f Mx: %f My: %f Sum: %f X1: %f Y1: %f Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels); 253 254 // add back offset of peak in primary image 255 // also offset from pixel index to pixel coordinate 256 // (the calculation above uses pixel index instead of coordinate) 257 // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords 258 259 // we only update the centroid if the position is not supplied from elsewhere 260 bool skipCentroid = false; 261 skipCentroid |= (source->mode & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions 262 skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions 263 264 if (skipCentroid) { 265 source->moments->Mx = source->peak->xf; 266 source->moments->My = source->peak->yf; 267 } else { 268 source->moments->Mx = Mx + xGuess; 269 source->moments->My = My + yGuess; 270 } 271 272 source->moments->Sum = Sum; 273 source->moments->SN = Sum / sqrt(Var); 274 source->moments->Peak = peakPixel; 275 source->moments->nPixels = numPixels; 276 277 return true; 278 } 279 280 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) { 281 282 psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32); 283 284 for (int i = 0; i < sources->n; i++) { 285 pmSource *src = sources->data[i]; // Source of interest 286 if (!src || !src->moments) { 287 continue; 288 } 289 290 if (src->mode & PM_SOURCE_MODE_BLEND) { 291 continue; 292 } 293 294 if (!src->moments->nPixels) continue; 295 296 if (src->moments->SN < PSF_SN_LIM) continue; 297 298 // XXX put in Mxx,Myy cut based on clump location 299 300 psVectorAppend(radii, src->moments->Mrf); 301 } 302 303 // find the peak in this image 304 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN); 305 306 if (!psVectorStats (stats, radii, NULL, NULL, 0)) { 307 psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n"); 308 psFree(stats); 309 return NAN; 310 } 311 312 float minRadius = stats->sampleMedian; 313 314 psFree(radii); 315 psFree(stats); 316 return minRadius; 317 } 318 319 bool pmSourceMomentsHighOrder (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal) { 320 321 // this function assumes the sky has been well-subtracted for the image 322 float Sum = 0.0; 323 float R2 = PS_SQR(radius); 324 float minSN2 = PS_SQR(minSN); 325 float rsigma2 = 0.5 / PS_SQR(sigma); 326 116 327 // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates 117 // Xn = SUM (x - xc)^n * (z - sky) 328 // Xn = SUM (x - xc)^n * (z - sky) -- note that sky is 0.0 by definition here 118 329 float XX = 0.0; 119 330 float XY = 0.0; … … 129 340 float YYYY = 0.0; 130 341 131 Sum = 0.0; // the second pass may include slightly different pixels, re-determine Sum132 133 // float dX = source->moments->Mx - source->peak->xf;134 // float dY = source->moments->My - source->peak->yf;135 // float dR = hypot(dX, dY);136 // float Xo = (dR < 2.0) ? source->moments->Mx : source->peak->xf;137 // float Yo = (dR < 2.0) ? source->moments->My : source->peak->yf;138 342 float Xo = source->moments->Mx; 139 343 float Yo = source->moments->My; … … 154 358 155 359 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row]; 156 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];157 360 158 361 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) { … … 173 376 if (r2 > R2) continue; 174 377 175 float fDiff = *vPix - sky;378 float fDiff = *vPix; 176 379 float pDiff = fDiff; 177 380 float wDiff = *vWgt; … … 181 384 // stars. 182 385 if (PS_SQR(pDiff) < minSN2*wDiff) continue; 183 if ((minSN > 0.0) && (pDiff < 0)) continue; //386 if ((minSN > 0.0) && (pDiff < 0)) continue; 184 387 185 388 // Apply a Gaussian window function. Be careful with the window function. S/N 186 // weighting over weights the sky for faint sources389 // weighting over-weights the sky for faint sources 187 390 if (sigma > 0.0) { 188 391 float z = r2 * rsigma2; … … 230 433 XYYY += xyyy; 231 434 YYYY += yyyy; 232 233 // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)234 // XXX float r = sqrt(r2);235 // XXX float rf = r * fDiff;236 // XXX float rh = sqrt(r) * fDiff;237 // XXX float rs = fDiff;238 // XXX239 // XXX float rfw = r * pDiff;240 // XXX float rhw = sqrt(r) * pDiff;241 // XXX242 // XXX RF += rf;243 // XXX RH += rh;244 // XXX RS += rs;245 // XXX246 // XXX RFW += rfw;247 // XXX RHW += rhw;248 435 } 249 436 } … … 263 450 source->moments->Myyyy = YYYY/Sum; 264 451 265 // *** now calculate the 1st radial moment (for kron flux) -- symmetrical averaging 452 return true; 453 } 454 455 bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal) { 456 266 457 267 458 float **vPix = source->pixels->data.F32; 268 float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32;269 459 psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 270 460 … … 272 462 float RH = 0.0; 273 463 float RS = 0.0; 464 465 // centroid around which to calculate the moments 466 float Xo = source->moments->Mx; 467 float Yo = source->moments->My; 468 469 // center of mass in subimage. Note: the calculation below uses pixel index, so we correct 470 // xCM, yCM from pixel coords to pixel index here. 471 float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage 472 float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 473 474 float R2 = PS_SQR(radius); 274 475 275 476 for (psS32 row = 0; row < source->pixels->numRows ; row++) { … … 304 505 if (r2 > R2) continue; 305 506 306 float fDiff1 = vPix[row][col] - sky;307 float fDiff2 = vPix[yFlip][xFlip] - sky;507 float fDiff1 = vPix[row][col]; 508 float fDiff2 = vPix[yFlip][xFlip]; 308 509 float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2)); 309 510 … … 329 530 kronRefRadius = MIN(radius, kronRefRadius); 330 531 } 331 source->moments->Mrf = kronRefRadius; 332 333 // *** now calculate the kron flux values using the 1st radial moment 334 335 float radKinner = 1.0*kronRefRadius; 336 float radKron = 2.5*kronRefRadius; 337 float radKouter = 4.0*kronRefRadius; 532 533 // if source is externally supplied and it already has a finite Mrf do not change it 534 if (! ((source->mode & PM_SOURCE_MODE_EXTERNAL) && isfinite(source->moments->Mrf))) { 535 source->moments->Mrf = kronRefRadius; 536 } 537 538 return true; 539 } 540 541 bool pmSourceMomentsKronFluxes (pmSource *source, float sigma, float minSN, psImageMaskType maskVal) { 542 543 float **vPix = source->pixels->data.F32; 544 float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32; 545 psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 546 547 float radKinner = 1.0*source->moments->Mrf; 548 float radKron = 2.5*source->moments->Mrf; 549 float radKouter = 4.0*source->moments->Mrf; 338 550 339 551 int nKronPix = 0; … … 341 553 int nInner = 0; 342 554 int nOuter = 0; 343 Sum = Var = 0.0; 555 556 float Sum = 0.0; 557 float Var = 0.0; 558 float SumCore = 0.0; 559 float VarCore = 0.0; 344 560 float SumInner = 0.0; 345 561 float SumOuter = 0.0; 562 563 // centroid around which to calculate the moments 564 float Xo = source->moments->Mx; 565 float Yo = source->moments->My; 566 567 // center of mass in subimage. Note: the calculation below uses pixel index, so we correct 568 // xCM, yCM from pixel coords to pixel index here. 569 float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage 570 float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage 571 572 float minSN2 = PS_SQR(minSN); 346 573 347 574 // calculate the Kron flux, and related fluxes (NO symmetrical averaging) … … 362 589 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff); 363 590 364 float fDiff1 = vPix[row][col] - sky;591 float fDiff1 = vPix[row][col]; 365 592 float pDiff = fDiff1; 366 593 float wDiff = vWgt[row][col]; … … 376 603 Var += wDiff; 377 604 nKronPix ++; 378 // if (beVerbose) fprintf (stderr, "mome: %d %d %f %f %f\n", col, row, sky, *vPix, Sum);379 605 } 380 606 … … 397 623 } 398 624 // *** should I rescale these fluxes by pi R^2 / nNpix? 399 // XXX source->moments->KronCore = SumCore * M_PI * PS_SQR(sigma) / nCorePix;400 // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;401 // XXX source->moments->KronFlux = Sum * M_PI *PS_SQR(radKron) / nKronPix;402 // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI *PS_SQR(radKron) / nKronPix;403 // XXX source->moments->KronFinner = SumInner* M_PI * (PS_SQR(radKron) - PS_SQR(radKinner)) / nInner;404 // XXX source->moments->KronFouter = SumOuter* M_PI * (PS_SQR(radKouter) - PS_SQR(radKron)) / nOuter;625 // XXX source->moments->KronCore = SumCore * M_PI * PS_SQR(sigma) / nCorePix; 626 // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix; 627 // XXX source->moments->KronFlux = Sum * M_PI * PS_SQR(radKron) / nKronPix; 628 // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix; 629 // XXX source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron) - PS_SQR(radKinner)) / nInner; 630 // XXX source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) - PS_SQR(radKron)) / nOuter; 405 631 406 632 source->moments->KronCore = SumCore; … … 408 634 source->moments->KronFlux = Sum; 409 635 source->moments->KronFluxErr = sqrt(Var); 410 source->moments->KronFinner = SumInner;411 source->moments->KronFouter = SumOuter;636 source->moments->KronFinner = SumInner; 637 source->moments->KronFouter = SumOuter; 412 638 413 639 // XXX not sure I should save this here... … … 416 642 source->moments->KronRadiusPSF = source->moments->Mrf; 417 643 418 psTrace ("psModules.objects", 4, "Mrf: %f KronFlux: %f Mxx: %f Mxy: %f Myy: %f Mxxx: %f Mxxy: %f Mxyy: %f Myyy: %f Mxxxx: %f Mxxxy: %f Mxxyy: %f Mxyyy: %f Mxyyy: %f\n",419 source->moments->Mrf, source->moments->KronFlux,420 source->moments->Mxx, source->moments->Mxy, source->moments->Myy,421 source->moments->Mxxx, source->moments->Mxxy, source->moments->Mxyy, source->moments->Myyy,422 source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);423 424 psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f My: %f Sum: %f Mxx: %f Mxy: %f Myy: %f sky: %f Npix: %d\n",425 source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx, source->moments->My, Sum, source->moments->Mxx, source->moments->Mxy, source->moments->Myy, sky, source->moments->nPixels);426 427 return(true);428 }429 430 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {431 432 // First Pass: calculate the first moments (these are subtracted from the coordinates below)433 // Sum = SUM (z - sky)434 // X1 = SUM (x - xc)*(z - sky)435 // .. etc436 437 float sky = 0.0;438 439 float peakPixel = -PS_MAX_F32;440 psS32 numPixels = 0;441 float Sum = 0.0;442 float Var = 0.0;443 float X1 = 0.0;444 float Y1 = 0.0;445 float R2 = PS_SQR(radius);446 float minSN2 = PS_SQR(minSN);447 float rsigma2 = 0.5 / PS_SQR(sigma);448 449 float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage450 float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage451 452 // we are guaranteed to have a valid pixel and variance at this location (right? right?)453 // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);454 // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");455 // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");456 // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");457 458 // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should459 // not depend on the fractional pixel location of the source. However, the aperture460 // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel461 // position of the expected centroid462 463 for (psS32 row = 0; row < source->pixels->numRows ; row++) {464 465 float yDiff = row + 0.5 - yPeak;466 if (fabs(yDiff) > radius) continue;467 468 float *vPix = source->pixels->data.F32[row];469 float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row];470 471 psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];472 // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];473 474 for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {475 if (vMsk) {476 if (*vMsk & maskVal) {477 vMsk++;478 continue;479 }480 vMsk++;481 }482 if (isnan(*vPix)) continue;483 484 float xDiff = col + 0.5 - xPeak;485 if (fabs(xDiff) > radius) continue;486 487 // radius is just a function of (xDiff, yDiff)488 float r2 = PS_SQR(xDiff) + PS_SQR(yDiff);489 if (r2 > R2) continue;490 491 float pDiff = *vPix - sky;492 float wDiff = *vWgt;493 494 // skip pixels below specified significance level. for a PSFs, this495 // over-weights the wings of bright stars compared to those of faint stars.496 // for the estimator used for extended source analysis (where the window497 // function is allowed to be arbitrarily large), we need to clip to avoid498 // negative second moments.499 if (PS_SQR(pDiff) < minSN2*wDiff) continue; //500 if ((minSN > 0.0) && (pDiff < 0)) continue; //501 502 // Apply a Gaussian window function. Be careful with the window function. S/N503 // weighting over weights the sky for faint sources504 if (sigma > 0.0) {505 float z = r2*rsigma2;506 assert (z >= 0.0);507 float weight = exp(-z);508 509 wDiff *= weight;510 pDiff *= weight;511 }512 513 Var += wDiff;514 Sum += pDiff;515 516 float xWght = xDiff * pDiff;517 float yWght = yDiff * pDiff;518 519 X1 += xWght;520 Y1 += yWght;521 522 peakPixel = PS_MAX (*vPix, peakPixel);523 numPixels++;524 }525 }526 527 // if we have less than (1/4) of the possible pixels (in circle or box), force a retry528 int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0);529 530 // XXX EAM - the limit is a bit arbitrary. make it user defined?531 if ((numPixels < minPixels) || (Sum <= 0)) {532 psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);533 return (false);534 }535 536 // calculate the first moment.537 float Mx = X1/Sum;538 float My = Y1/Sum;539 if ((fabs(Mx) > radius) || (fabs(My) > radius)) {540 psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);541 return (false);542 }543 if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) {544 psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y);545 }546 547 psTrace ("psModules.objects", 5, "id: %d, sky: %f Mx: %f My: %f Sum: %f X1: %f Y1: %f Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);548 549 // add back offset of peak in primary image550 // also offset from pixel index to pixel coordinate551 // (the calculation above uses pixel index instead of coordinate)552 // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords553 554 // we only update the centroid if the position is not supplied from elsewhere555 bool skipCentroid = false;556 skipCentroid |= (source->mode & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions557 skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions558 559 if (skipCentroid) {560 source->moments->Mx = source->peak->xf;561 source->moments->My = source->peak->yf;562 } else {563 source->moments->Mx = Mx + xGuess;564 source->moments->My = My + yGuess;565 }566 567 source->moments->Sum = Sum;568 source->moments->SN = Sum / sqrt(Var);569 source->moments->Peak = peakPixel;570 source->moments->nPixels = numPixels;571 572 644 return true; 573 645 } 574 575 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) {576 577 psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32);578 579 for (int i = 0; i < sources->n; i++) {580 pmSource *src = sources->data[i]; // Source of interest581 if (!src || !src->moments) {582 continue;583 }584 585 if (src->mode & PM_SOURCE_MODE_BLEND) {586 continue;587 }588 589 if (!src->moments->nPixels) continue;590 591 if (src->moments->SN < PSF_SN_LIM) continue;592 593 // XXX put in Mxx,Myy cut based on clump location594 595 psVectorAppend(radii, src->moments->Mrf);596 }597 598 // find the peak in this image599 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);600 601 if (!psVectorStats (stats, radii, NULL, NULL, 0)) {602 psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");603 psFree(stats);604 return NAN;605 }606 607 float minRadius = stats->sampleMedian;608 609 psFree(radii);610 psFree(stats);611 return minRadius;612 }613 -
trunk/psModules/src/objects/pmSourcePhotometry.c
r34498 r36375 113 113 source->apFluxErr = NAN; 114 114 115 pmModelStatus badModel = PM_MODEL_STATUS_NONE; 116 badModel |= PM_MODEL_STATUS_BADARGS; 117 badModel |= PM_MODEL_STATUS_OFFIMAGE; 118 badModel |= PM_MODEL_STATUS_NAN_CHISQ; 119 badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS; 120 badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID; 121 badModel |= PM_MODEL_PCM_FAIL_GUESS; 122 115 123 // XXXXXX review: 116 124 // Select the 'best' model -- this is used for PSF_QF,_PERFECT & ???. isPSF is true if this … … 162 170 for (int i = 0; i < source->modelFits->n; i++) { 163 171 pmModel *model = source->modelFits->data[i]; 164 if (model->flags & PM_MODEL_STATUS_BADARGS) continue;172 if (model->flags & badModel) continue; 165 173 status = pmSourcePhotometryModel (&model->mag, NULL, model); 166 174 if (model == source->modelEXT) foundEXT = true; … … 902 910 } 903 911 912 bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal) 913 { 914 PS_ASSERT_PTR_NON_NULL(source, false); 915 PS_ASSERT_PTR_NON_NULL(model, false); 916 917 float dC = 0.0; 918 int Npix = 0; 919 920 psVector *params = model->params; 921 psImage *image = source->pixels; 922 psImage *modelFlux = source->modelFlux; 923 psImage *mask = source->maskObj; 924 psImage *variance = source->variance; 925 926 float Io = params->data.F32[PM_PAR_I0]; 927 928 for (int iy = 0; iy < image->numRows; iy++) { 929 for (int ix = 0; ix < image->numCols; ix++) { 930 931 // skip pixels which are masked 932 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) continue; 933 934 if (variance->data.F32[iy][ix] <= 0) continue; 935 936 dC += PS_SQR (image->data.F32[iy][ix] - Io*modelFlux->data.F32[iy][ix]) / variance->data.F32[iy][ix]; 937 Npix ++; 938 } 939 } 940 model->nPix = Npix; 941 model->nDOF = Npix - model->nPar; 942 model->chisq = dC; 943 model->chisqNorm = dC / model->nDOF; 944 945 return (true); 946 } 947 904 948 double pmSourceModelWeight(const pmSource *Mi, int term, const pmSourceFitVarMode fitVarMode, const float covarFactor, psImageMaskType maskVal) 905 949 {
Note:
See TracChangeset
for help on using the changeset viewer.
